package com.iwhalecloud.citybrain.flow.platform.manager.application.event;

import com.alibaba.fastjson.JSON;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.EventCallTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.CommonTaskEventProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.ParseRenderedVariable;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.exception.EventCallException;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.eventconfig.DeployedEventConfigDomain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author: liyang
 * @date: 2021/11/10 16:27
 */
@Slf4j
@Service
public class NodeOperEventCaller{

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private CommonTaskEventProcessor commonTaskEventProcessor;

    @Autowired
    private NodeEventExecuter nodeEventExecuter;


    public EventResponse call(NodeOperEventReq nodeOperEventReq) throws Exception {

        List<DeployedEventConfigDomain> deployedEventConfigDomainList = commonTaskEventProcessor.resolveEventConfigList(nodeOperEventReq.getProcessInstanceId(),nodeOperEventReq.getNodeCode()
                ,nodeOperEventReq.getEventType()+"_"+nodeOperEventReq.getNodeOperType());

        if (CollectionUtils.isNotEmpty(deployedEventConfigDomainList)){

            Map<String,Object> variables = runtimeService.getVariables(nodeOperEventReq.getProcessInstanceId());

            for (DeployedEventConfigDomain deployedEventConfigDomain : deployedEventConfigDomainList) {

                // 组装请求url中的任务实例ID以及处理人ID
                this.convertTaskIdAndAssignee(nodeOperEventReq, variables);

                // 请求的地址url
                String url = ParseRenderedVariable.parseRenderedVariable(deployedEventConfigDomain.getCallbackContent(),variables);

                // 请求参数体
                String requestBody = ParseRenderedVariable.parseRenderedVariable(deployedEventConfigDomain.getRequestBody(),variables);

//                requestBody = dealTaskIdAndAssignee(requestBody,nodeOperEventReq);
                log.info("convert after requestBody:{}",requestBody);
                if ( EventCallTypeEnum.SYNC.getType().equalsIgnoreCase(deployedEventConfigDomain.getCallMethod())){
                    EventResponse eventResponse = null;
                    try {
                        eventResponse = nodeEventExecuter.syncCall(url,requestBody);
                    } catch (EventCallException e) {
                        log.error("execute Sync EventCall Error:",e);
                        throw e;
                    }
                    if (Objects.isNull(eventResponse)){
                        throw new EventCallException("节点操作事件接口返回结果为空，无法判断接口调用是否成功，url="+url);
                    }
                    if (!eventResponse.isSuccess()){
                        StringBuilder msg = new StringBuilder("事件接口调用异常，异常信息为：");
                        if (StringUtils.isNotBlank(eventResponse.getMsg())){
                            msg.append(eventResponse.getMsg());
                        }
                        msg.append(",url=").append(url);
                        throw new EventCallException(msg.toString());
                    }
                    log.info(" sync NodeEvent Response:"+ JSON.toJSONString(eventResponse));
                }else{
                    try {
                        nodeEventExecuter.asyncCall(url,requestBody);
                    } catch (EventCallException e) {
                        log.error("execute Async EventCall Error:",e);
                    }
                    log.info("async Call Success!");
                }
            }
        }
        return null;
    }

    private String dealTaskIdAndAssignee(String requestBody, NodeOperEventReq nodeOperEventReq) {
        Map<String,Object> taskAssignee = new HashMap<>();
        if (StringUtils.isNotBlank(nodeOperEventReq.getTaskId())){
            taskAssignee.put("taskId",nodeOperEventReq.getTaskId());
        }
        if (StringUtils.isNotBlank(nodeOperEventReq.getUserCode())){
            taskAssignee.put("assignee",nodeOperEventReq.getUserCode());
        }
        log.info("taskAssignee:{}",taskAssignee);
        if (MapUtils.isNotEmpty(taskAssignee)){
            log.info("taskAssignee2:{}",taskAssignee);
            requestBody = ParseRenderedVariable.parseRenderedVariable(requestBody,taskAssignee);
        }
        log.info("dealTaskIdAndAssignee requestBody:{}",requestBody);
        return requestBody;
    }

    /**
     * 组装请求url中的任务实例ID以及处理人ID
     *
     * @param nodeOperEventReq
     * @param variables
     * @return
     */
    private void convertTaskIdAndAssignee(NodeOperEventReq nodeOperEventReq, Map<String,Object> variables) {
        // 封装数据对象不为空并且封装参数map不为空
        if(Objects.nonNull(nodeOperEventReq) && MapUtils.isNotEmpty(variables)) {
            if (StringUtils.isNotBlank(nodeOperEventReq.getTaskId())){
                variables.put("taskId",nodeOperEventReq.getTaskId());
            }
            if (StringUtils.isNotBlank(nodeOperEventReq.getUserCode())){
                variables.put("assignee",nodeOperEventReq.getUserCode());
            }
        }
    }
}
